/**
 * dbms-sjtu
 * BufferManager.java created at Aug 15, 2011
 */
package dbms.buffer;

import java.util.ArrayList;
import java.util.List;

/**
 * @author weapon
 *
 */
public class BufferManager {
	public List<Buffer> bufferPool = new ArrayList<Buffer>();
	//private int availableNum = 0;
	//private int firstAvailableBuffer = -1;
	
	public BufferManager(int bufferNum){
		//this.availableNum = bufferNum;
		//this.firstAvailableBuffer = 0;
		for(int i = 0; i < bufferNum; i++){
			this.bufferPool.add(new Buffer());
		}
	}
	
	/**
	 * flush all buffer contents, write them to database file,
	 * it runs at System exit.
	 */
	public void flushAll(){
		for(Buffer buffer : bufferPool){
			buffer.flush();
		}
	}
	 
	/**
	 * alloc a available buffer form buffer list.
	 * if all buffer are modified, we should use a strategy to remove a buffer from list.
	 * A strong replace strategy is very important, LRU, FIFO, or ...
	 * @return <b>a available buffer</b>
	 */
	public Buffer allocBuffer(){
		for(Buffer buffer : bufferPool){
			if(!buffer.isUsed()){
				return buffer;
			}
		} 
		//TODO no buffer available, we should call replaceStrategy alloc a new buffer
		return this.replaceStrategy();
	}
	
	/**
	 * the strategy for replace buffer page <br>
	 * Use LRU algorithm, readWriteTime stands the RW time of a buffer, we choose the least one.<br>
	 * then flush this buffer
	 * @return a buffer which will be replaced
	 */
	public Buffer replaceStrategy(){
		int minRWTime = Integer.MAX_VALUE;
		Buffer result = null;
		for(Buffer buffer : bufferPool){
			if(buffer.getReadWriteTime() < minRWTime){
				minRWTime = buffer.getReadWriteTime();
				result = buffer;
			}
		}
		result.flush();
		return result;
	}
	
	public Buffer findBufferByBlock(int block){
		for(Buffer buffer : this.bufferPool){
			if(buffer.getBlockNum() != -1){
				if(buffer.getBlockNum() == block){
					return buffer;
				}
			}
		}
		return null;
	}
}
